import { ILoadingHelper, IProjectSetting } from '@/core/interface';

/**
 * 加载助手
 *
 * @export
 * @class LoadingHelper
 * @implements {ILoadingHelper}
 */
export class LoadingHelper implements ILoadingHelper {
	/**
	 * Creates an instance of LoadingHelper.
	 * @param {('VIEW' | 'CONTROL')} type 加载助手类型
	 * @param {ILoadingHelper} [parent] 父级加载助手
	 * @param {Function} [bc] 开始加载回调
	 * @param {Function} [ec] 结束加载回调
	 * @memberof LoadingHelper
	 */
	constructor(
		private readonly type: 'VIEW' | 'CONTROL',
		private readonly parent?: ILoadingHelper,
		public bc?: Function,
		public ec?: Function
	) {}

	/**
	 * 是否加载中
	 *
	 * @type {boolean}
	 * @memberof LoadingHelper
	 */
	public isLoading = false;

	/**
	 * 加载状态绑定节点
	 *
	 * @private
	 * @type {(HTMLElement | null)}
	 * @memberof LoadingHelper
	 */
	private loadingBindElement: HTMLElement | null = null;

	/**
	 * 加载计数
	 *
	 * @private
	 * @type {number}
	 * @memberof LoadingHelper
	 */
	private loadingCount = 0;

	/**
	 * 开始加载
	 *
	 * @memberof LoadingHelper
	 */
	beginLoading(elementKey?: string): void {
		// 根据变量判断是否加载
		const projectSetting: IProjectSetting = App.getProjectSetting();
		const isOpenLoading = projectSetting.transitionSetting.openPageLoading;
		this.loadingCount += 1;
		if (this.isLoading || !isOpenLoading) {
			return;
		}
		this.isLoading = true;
		this.createLoadingMask(elementKey);
		if (this.parent) {
			this.parent.beginLoading();
		}
		if (this.bc && this.bc instanceof Function) {
			this.bc();
		}
	}

	/**
	 * 结束加载
	 *
	 * @return {*}  {void}
	 * @memberof LoadingHelper
	 */
	endLoading(): void {
		if (!this.isLoading && this.loadingCount === 0) {
			return;
		}
		this.isLoading = false;
		this.loadingCount -= 1;
		this.destroyLoadingMask();
		if (this.parent) {
			this.parent.endLoading();
		}
		if (this.ec && this.ec instanceof Function) {
			this.ec();
		}
	}

	/**
	 * 创建加载遮罩
	 *
	 * @private
	 * @param {string} [elementKey]
	 * @return {*}
	 * @memberof LoadingHelper
	 */
	private createLoadingMask(elementKey?: string) {
		if (this.type !== 'CONTROL' || !elementKey) {
			return;
		}
		let element: HTMLElement | null = null;
		try {
			element = document.getElementById(elementKey);
		} catch (error) {}
		if (!element) {
			return;
		}
		element.style.pointerEvents = 'none';
		const loadingMask = document.createElement('div');
		loadingMask.classList.add(
			'loading-mask',
			`loading-mask-${this.type.toLowerCase()}`
		);
		loadingMask.id = `loading-mask-${elementKey}`;
		const loadingMaskSpin = `
      <div class="loading-mask__spin">
        <span class="loading-mask__spin-container">
          <span class="loading-mask__spin-item"></span>
          <span class="loading-mask__spin-item"></span>
          <span class="loading-mask__spin-item"></span>
          <span class="loading-mask__spin-item"></span>
        </span>
      <div class="loading-mask__blur"></div>`;
		loadingMask.innerHTML = loadingMaskSpin;
		element.appendChild(loadingMask);
		this.loadingBindElement = element;
	}

	/**
	 * 销毁加载遮罩
	 *
	 * @private
	 * @memberof LoadingHelper
	 */
	private destroyLoadingMask() {
		if (this.loadingBindElement) {
			this.loadingBindElement.style.pointerEvents = 'auto';
			const children = this.loadingBindElement.children as HTMLCollection;
            for (let i = 0; i < children.length; i++) {
                if (children[i] && children[i].classList && children[i].classList.contains('loading-mask')) {
                    children[i].remove();
                }
            }
		}
	}
}
